package com.yeskery.nut.bean;

import com.yeskery.nut.annotation.bean.Lazy;
import com.yeskery.nut.annotation.bean.LazyInitialized;
import com.yeskery.nut.annotation.bean.Qualifier;
import com.yeskery.nut.aop.DefaultProxyObjectContext;
import com.yeskery.nut.aop.ProxyObjectContext;
import com.yeskery.nut.aop.ProxyObjectHolder;
import com.yeskery.nut.bean.aware.ApplicationContextAware;
import com.yeskery.nut.bean.aware.BeanNameAware;
import com.yeskery.nut.bean.aware.ClassLoaderAware;
import com.yeskery.nut.bean.aware.EnvironmentAware;
import com.yeskery.nut.bean.destroy.BeanProxyDestroy;
import com.yeskery.nut.bean.destroy.DisposableBeanInterfaceProxyDestroy;
import com.yeskery.nut.bean.destroy.PreDestroyAnnotationProxyDestroy;
import com.yeskery.nut.bean.initialized.LazyBeanProxyInitialized;
import com.yeskery.nut.bean.initialized.LazyInitializedAnnotationProxyInitialized;
import com.yeskery.nut.bean.initialized.LazyInitializingBeanInterfaceProxyInitialized;
import com.yeskery.nut.core.Environment;
import com.yeskery.nut.core.Order;
import com.yeskery.nut.scan.BeanAnnotationScanMetadata;
import com.yeskery.nut.util.BeanUtils;
import com.yeskery.nut.util.ClassLoaderUtils;
import com.yeskery.nut.util.ReflectUtils;
import com.yeskery.nut.util.StringUtils;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;
import java.util.*;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;

/**
 * 基础的应用上下文
 * @author sprout
 * 2022-06-20 14:47
 */
public abstract class BaseApplicationContext implements ApplicationContext, FactoryBeanRegister, BeanIterable {

    /** 日志对象 */
    private static final Logger logger = Logger.getLogger(BaseApplicationContext.class.getName());

    /** 内部类或lambda表达式标志符 */
    private static final String INNER_CLASS_SYMBOL = "$";

    /** 运行状态 */
    private static final int RUNNING = 1;

    /** 关闭状态 */
    private static final int CLOSED = 0;

    /** 代理对象上下文 */
    private final ProxyObjectContext proxyObjectContext = new DefaultProxyObjectContext(this);

    /** 已注册的bean名称缓存set */
    private final Set<String> registeredBeanNameSet = new HashSet<>();

    /** 已注册的bean类型缓存 */
    private final Set<Class<?>> registeredBeanTypeSet = new HashSet<>();

    /** 单例bean名称缓存map */
    private final Map<String, Object> singletonBeanNameCacheMap = new HashMap<>();

    /** 单例bean类型缓存map */
    private final Map<Class<?>, Collection<Object>> singletonBeanClassCacheMap = new HashMap<>();

    /** 多例bean名称缓存map */
    private final Map<String, BeanDefinition> prototypeBeanNameCacheMap = new HashMap<>();

    /** 多例bean类型缓存map */
    private final Map<Class<?>, Collection<BeanDefinition>> prototypeBeanClassCacheMap = new HashMap<>();

    /** 早期创建bean缓存map */
    private final Map<String, BeanHolder> earlyBeanCreationMap = new HashMap<>();

    /** bean代理销毁列表 */
    private final List<BeanProxyDestroy> beanProxyDestroyList = new LinkedList<>();

    /** bean延迟初始化列表 */
    private final List<LazyBeanProxyInitialized> lazyBeanProxyInitializedList = new LinkedList<>();

    /** 父级应用上下文 */
    private ApplicationContext parentApplicationContext;

    /** 所有Bean扫描元数据类型 */
    private Collection<BeanAnnotationScanMetadata> beanAnnotationScanMetadata;

    /** 应用上下文运行状态 */
    private volatile int status = RUNNING;

    /** 是否初始化 */
    private volatile boolean isInitialize = false;

    /**
     * 构建基础的应用上下文
     */
    public BaseApplicationContext() {
        singletonBeanNameCacheMap.put("applicationContext", this);
        registeredBeanNameSet.add("applicationContext");
        singletonBeanClassCacheMap.put(ApplicationContext.class, Collections.singleton(this));
    }

    /**
     * 构建基础的应用上下文
     * @param parentApplicationContext 父级应用上下文
     */
    public BaseApplicationContext(ApplicationContext parentApplicationContext) {
        this();
        this.parentApplicationContext = parentApplicationContext;
    }

    @Override
    public Object getBean(String beanName) throws NoSuchBeanException {
        if (parentApplicationContext != null) {
            try {
                Object bean = parentApplicationContext.getBean(beanName);
                if (bean != null) {
                    return bean;
                }
            } catch (NoSuchBeanException e) {
                // not to deal.
            }
        }
        if (!registeredBeanNameSet.contains(beanName)) {
            throw new NoSuchBeanException("No Such Bean Name[" + beanName + "].");
        }
        BeanHolder beanHolder = earlyBeanCreationMap.get(beanName);
        if (beanHolder != null) {
            return beanHolder.getObject();
        }

        Object bean = singletonBeanNameCacheMap.get(beanName);
        if (bean != null) {
            return bean;
        }

        BeanDefinition beanDefinition = prototypeBeanNameCacheMap.get(beanName);
        if (beanDefinition != null) {
            Object instance = createBeanInstance(beanDefinition);
            beanAttributePadding(instance);

            executeBeanAwareInterfaceMethod(instance, beanDefinition);
            executeBeanInitializeMethod(instance, beanDefinition);
            return instance;
        }
        throw new NoSuchBeanException("No Such Bean Name[" + beanName + "].");
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> T getBean(String beanName, Class<T> beanClass) throws NoSuchBeanException {
        return (T) getBean(beanName);
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> T getBean(Class<T> beanClass) throws NoSuchBeanException {
        if (parentApplicationContext != null) {
            try {
                T bean = parentApplicationContext.getBean(beanClass);
                if (bean != null) {
                    return bean;
                }
            } catch (NoSuchBeanException e) {
                // not to deal.
            }
        }
        Collection<T> beans = doGetBeans(beanClass, false, true);
        Collection<Object> objects = singletonBeanClassCacheMap.get(beanClass);
        int primaryHit = 0;
        PrimaryBeanHolder primaryBeanHolder = null;
        if (objects != null) {
            for (Object object : objects) {
                if (object != null) {
                    if (object instanceof PrimaryBeanHolder) {
                        primaryBeanHolder = (PrimaryBeanHolder) object;
                        beans.add((T) primaryBeanHolder.getBean());
                        primaryHit++;
                    } else {
                        beans.add((T) object);
                    }
                }
            }
        }
        if (primaryHit > 1) {
            throw new NoSuchBeanException("Multi Primary Bean Class[" + beanClass.getName() + "] Found.");
        } else if (beans.isEmpty()) {
            throw new NoSuchBeanException("No Such Bean Class[" + beanClass.getName() + "].");
        } else if (beans.size() > 1 && primaryBeanHolder == null) {
            throw new NoSuchBeanException("Multi Bean Class[" + beanClass.getName() + "] Found.");
        }
        return (T) (primaryBeanHolder != null ? primaryBeanHolder.getBean() : ((List<?>) beans).get(0));
    }

    @Override
    public <T> Collection<T> getBeans(Class<T> beanClass) {
        if (parentApplicationContext != null) {
            Collection<T> beans = parentApplicationContext.getBeans(beanClass);
            if (beans != null && !beans.isEmpty()) {
                return beans;
            }
        }
        return doGetBeans(beanClass, true, true);
    }

    @Override
    public void close() throws IOException {
        if (status == CLOSED) {
            return;
        }
        status = CLOSED;
        for (BeanProxyDestroy beanProxyDestroy : beanProxyDestroyList) {
            try {
                beanProxyDestroy.destroy();
            } catch (Exception e) {
                logger.logp(Level.SEVERE, beanProxyDestroy.getClass().getName(), "destroy",
                        "Bean Destroy Method Execute Fail, Bean Type [" + beanProxyDestroy.getBeanType().getName()
                                + "] Bean Name [" + beanProxyDestroy.getBeanName() + "].", e);
            }
        }
        if (parentApplicationContext != null) {
            parentApplicationContext.close();
        }
    }

    @Override
    public synchronized void registerBean(String beanName, boolean primary, Object bean, Class<?>... classes) {
        if (status == CLOSED) {
            throw new BeanException("Application Already Closed.");
        }
        if (registeredBeanNameSet.contains(beanName)) {
            throw new BeanAlreadyRegisterException("Bean Name[" + beanName + "]  Existed.");
        }
        registeredBeanNameSet.add(beanName);
        singletonBeanNameCacheMap.put(beanName, bean);

        if (bean.getClass().getName().contains(INNER_CLASS_SYMBOL) && classes.length == 0) {
            throw new BeanException("Class [" + bean.getClass().getName()
                    + "] Is Inner Class Or Lambda Function Expression, Need Given Class Name.");
        }
        singletonBeanClassCacheMap.computeIfAbsent(bean.getClass(), k -> new ArrayList<>()).add(bean);

        Set<Class<?>> interfaces = Arrays.stream(classes).collect(Collectors.toSet());
        interfaces.addAll(Arrays.asList(BeanUtils.getDeclaredInterfaces(bean.getClass())));

        for (Class<?> interfaceClass : interfaces) {
            if (!interfaceClass.equals(bean.getClass())) {
                Collection<Object> interfaceClassObjects = singletonBeanClassCacheMap.computeIfAbsent(interfaceClass, k -> new ArrayList<>());
                if (!interfaceClassObjects.contains(bean)) {
                    if (primary) {
                        ((ArrayList<Object>) interfaceClassObjects).add(0, new PrimaryBeanHolder(bean));
                    } else {
                        interfaceClassObjects.add(bean);
                    }
                }
            }
        }

        BeanDefinition beanDefinition = new BeanDefinition();
        beanDefinition.setBeanName(beanName);
        beanDefinition.setBeanClass(bean.getClass());
        executeBeanExtendMethods(bean, beanDefinition);
    }

    @Override
    public void setBeanAnnotationScanMetadata(Collection<BeanAnnotationScanMetadata> beanAnnotationScanMetadata) {
        if (this.beanAnnotationScanMetadata != null) {
            throw new BeanException("BeanAnnotationScanMetadata Already Exist.");
        }
        this.beanAnnotationScanMetadata = beanAnnotationScanMetadata;
    }

    @Override
    public synchronized void registerBean(BeanDefinition beanDefinition) {
        if (status == CLOSED) {
            throw new BeanException("Application Already Closed.");
        }
        if (beanDefinition == null) {
            throw new BeanException("BeanDefinition Can Not Be Null.");
        }
        if (StringUtils.isEmpty(beanDefinition.getBeanName())) {
            throw new BeanException("Bean Name Can Not Be Empty.");
        }
        if (beanDefinition.getBeanClass() == null) {
            throw new BeanException("Bean Class Can Not Be Null.");
        }
        if (registeredBeanNameSet.contains(beanDefinition.getBeanName())) {
            throw new BeanException("Cyclic Dependence Or Bean Already Registered, Bean Name["
                    + beanDefinition.getBeanName() + "] Class[" + beanDefinition.getBeanClass().getName() + "].");
        }
        registeredBeanNameSet.add(beanDefinition.getBeanName());

        Object bean = null;
        if (beanDefinition.isSingleton()) {
            if (beanDefinition.isLazy()) {
                Constructor<?> constructor = beanDefinition.getConstructor();
                if (constructor.getParameterCount() == 0) {
                    bean = getProxyObjectContext().createProxyObject(beanDefinition.getBeanClass(),
                            new LazyComponentInitializeWrapInvocationHandler(this, beanDefinition));
                } else {
                    Object[] arguments = new Object[constructor.getParameterCount()];
                    bean = getProxyObjectContext().createProxyObject(beanDefinition.getBeanClass(), constructor.getParameterTypes(),
                            arguments, new LazyComponentInitializeWrapInvocationHandler(this, beanDefinition));
                }
                singletonBeanNameCacheMap.put(beanDefinition.getBeanName(), bean);
            } else {
                bean = createBeanInstance(beanDefinition);
                earlyBeanCreationMap.put(beanDefinition.getBeanName(), new BeanHolder(beanDefinition.getBeanClass(), bean));
            }
        } else {
            prototypeBeanNameCacheMap.put(beanDefinition.getBeanName(), beanDefinition);
            Collection<BeanDefinition> beanDefinitions = prototypeBeanClassCacheMap.computeIfAbsent(beanDefinition.getBeanClass(), k -> new ArrayList<>());
            if (!beanDefinitions.contains(beanDefinition)) {
                beanDefinitions.add(beanDefinition);
            }
        }

        if (beanDefinition.getDepends() != null) {
            for (BeanAttribute beanAttribute: beanDefinition.getDepends()) {
                if (StringUtils.isEmpty(beanAttribute.getName())) {
                    if (!registeredBeanTypeSet.contains(beanAttribute.getType())) {
                        registerBean(beanAttribute.getType());
                        registeredBeanTypeSet.add(beanAttribute.getType());
                    }
                } else {
                    if (!containBean(beanAttribute.getName())) {
                        registerBean(beanAttribute.getType());
                        registeredBeanTypeSet.add(beanAttribute.getType());
                    }
                }
            }
        }

        if (bean != null && beanDefinition.isSingleton()) {
            initializedBean(bean, beanDefinition, beanDefinition.isLazy());
        }
    }

    @Override
    public void registerBean(BeanAnnotationScanMetadata beanAnnotationMetadata) {
        registerBean(beanAnnotationMetadata.getType());
    }

    @Override
    public boolean containBean(Class<?> beanClass) {
        return !getBeans(beanClass).isEmpty();
    }

    @Override
    public boolean containBean(String beanName) {
        try {
            return getBean(beanName) != null;
        } catch (NoSuchBeanException e) {
            return false;
        }
    }

    @Override
    public Map<String, Object> getSingletonBeans() {
        return singletonBeanNameCacheMap;
    }

    @Override
    public Map<String, BeanDefinition> getPrototypeBeanDefinitions() {
        return prototypeBeanNameCacheMap;
    }

    /**
     * 创建bean实例
     * @param beanDefinition bean定义对象
     * @return bean实例
     */
    public Object createBeanInstance(BeanDefinition beanDefinition) {
        Constructor<?> constructor = beanDefinition.getConstructor();
        Parameter[] parameters = constructor.getParameters();
        if (parameters.length == 0) {
            return doCreateBeanInstance(beanDefinition, () -> {
                try {
                    return constructor.newInstance();
                } catch (Exception e) {
                    throw new BeanException("Bean Creation Fail.", e);
                }
            });
        } else {
            Object[] params = new Object[parameters.length];
            for (int i = 0; i < parameters.length; i++) {
                Parameter parameter = parameters[i];
                String name = null;
                if (parameter.isAnnotationPresent(Qualifier.class)) {
                    name = parameter.getAnnotation(Qualifier.class).value();
                }
                Lazy lazy = parameter.getAnnotation(Lazy.class);
                if (lazy == null) {
                    lazy = constructor.getAnnotation(Lazy.class);
                }
                Type genericType = parameter.getParameterizedType();
                try {
                    Object value;
                    if (beanDefinition.isSingleton() && lazy != null && lazy.value()) {
                        Class<?> parameterClass = parameter.getType();
                        if (parameterClass.isInterface()) {
                            value = getProxyObjectContext().createProxyObject(parameterClass,
                                    new LazyInjectWrapInvocationHandler(this, parameterClass, name));
                        } else {
                            Constructor<?> beanFitConstructor = ReflectUtils.getBeanFitConstructor(parameterClass);
                            if (beanFitConstructor.getParameterCount() == 0) {
                                value = getProxyObjectContext().createProxyObject(parameterClass,
                                        new LazyInjectWrapInvocationHandler(this, parameterClass, name));
                            } else {
                                Class<?>[] argumentTypes = beanFitConstructor.getParameterTypes();
                                Object[] arguments = new Object[argumentTypes.length];
                                value = getProxyObjectContext().createProxyObject(parameterClass,argumentTypes, arguments,
                                        new LazyInjectWrapInvocationHandler(this, parameterClass, name));
                            }
                        }
                    } else {
                        value = BeanUtils.getDependBeanObject(this, name, genericType);
                    }
                    params[i] = value;
                } catch (NoSuchBeanException e) {
                    Class<?> type = BeanUtils.getDependBeanType(genericType);
                    beanAnnotationScanMetadata.stream().filter(t -> type.isAssignableFrom(t.getType())).forEach(this::registerBean);
                    Object value = BeanUtils.getDependBeanObject(this, name, genericType);
                    params[i] = value;
                }
            }
            return doCreateBeanInstance(beanDefinition, () -> {
                try {
                    return constructor.newInstance(params);
                } catch (Exception e) {
                    throw new BeanException("Bean Creation Fail.", e);
                }
            }, params);
        }
    }

    /**
     * 获取代理上下文对象
     * @return 代理上下文对象
     */
    public ProxyObjectContext getProxyObjectContext() {
        return proxyObjectContext;
    }

    /**
     * 应用启动后处理方法扩展
     */
    public void afterApplicationInitialized() {
        if (isInitialize) {
            throw new IllegalStateException("ApplicationContext Already Initialized.");
        }
        executeAfterApplicationInitialized();
        isInitialize = true;
    }

    /**
     * 属性填充
     * @param object bean实例对象
     */
    public abstract void beanAttributePadding(Object object);

    /**
     * 获取bean定义信息
     * @param clazz bean类型
     * @return bean定义信息
     */
    protected abstract BeanDefinition getBeanDefinition(Class<?> clazz);

    /**
     * 执行Bean的Aware接口扩展方法
     * @param bean bean对象
     * @param beanDefinition bean定义对象
     */
    protected void executeExtendBeanAwareInterfaceMethod(Object bean, BeanDefinition beanDefinition) {
    }

    /**
     * 应用启动后处理方法扩展
     */
    protected void executeAfterApplicationInitialized() {
        for (LazyBeanProxyInitialized lazyBeanProxyInitialized : lazyBeanProxyInitializedList) {
            try {
                lazyBeanProxyInitialized.initialize();
            } catch (Exception e) {
                logger.logp(Level.SEVERE, lazyBeanProxyInitialized.getClass().getName(), "initialize",
                        "Bean Lazy Initializing Method Execute Fail, Bean Type [" + lazyBeanProxyInitialized.getBeanType().getName()
                                + "] Bean Name [" + lazyBeanProxyInitialized.getBeanName() + "].", e);
            }
        }
        lazyBeanProxyInitializedList.clear();
    }

    /**
     * 获取bean构造器
     * @param beanClass bean类型
     * @return bean构造器
     */
    protected Constructor<?> getBeanFitConstructor(Class<?> beanClass) {
        return ReflectUtils.getBeanFitConstructor(beanClass);
    }

    /**
     * 获取所有Bean扫描元数据类型
     * @return 所有Bean扫描元数据类型
     */
    protected Collection<BeanAnnotationScanMetadata> getBeanAnnotationScanMetadata() {
        return beanAnnotationScanMetadata;
    }

    /**
     * 初始化bean
     * @param bean bean对象
     * @param beanDefinition bean定义对象
     * @param lazyBean 是否延迟加载bean
     */
    void initializedBean(Object bean, BeanDefinition beanDefinition, boolean lazyBean) {
        if (bean != null && beanDefinition.isSingleton()) {
            if (!lazyBean) {
                if (bean instanceof ProxyObjectHolder) {
                    ProxyObjectHolder proxyObjectHolder = (ProxyObjectHolder) bean;
                    beanAttributePadding(proxyObjectHolder.getProxyObject());
                    ReflectUtils.copyFields(proxyObjectHolder.getProxyObject(), proxyObjectHolder.getOriginalObject());
                    bean = proxyObjectHolder.getProxyObject();
                } else {
                    beanAttributePadding(bean);
                }
                earlyBeanCreationMap.remove(beanDefinition.getBeanName());
                singletonBeanNameCacheMap.put(beanDefinition.getBeanName(), bean);
            }
            Collection<Object> objects = singletonBeanClassCacheMap.computeIfAbsent(beanDefinition.getBeanClass(), k -> new ArrayList<>());
            objects.add(bean);

            Class<?>[] interfaces = BeanUtils.getDeclaredInterfaces(beanDefinition.getBeanClass());
            for (Class<?> interfaceClass : interfaces) {
                Collection<Object> interfaceClassObjects = singletonBeanClassCacheMap.computeIfAbsent(interfaceClass, k -> new ArrayList<>());
                if (beanDefinition.isPrimary()) {
                    ((ArrayList<Object>) interfaceClassObjects).add(0, new PrimaryBeanHolder(bean));
                } else {
                    interfaceClassObjects.add(bean);
                }
            }

            if (!lazyBean) {
                executeBeanExtendMethods(bean, beanDefinition);
            }
            registeredBeanTypeSet.add(beanDefinition.getBeanClass());
        }
    }

    /**
     * 执行bean扩展方法
     * @param bean bean对象
     * @param beanDefinition bean定义对象
     */
    private void executeBeanExtendMethods(Object bean, BeanDefinition beanDefinition) {
        executeBeanAwareInterfaceMethod(bean, beanDefinition);
        executeBeanInitializeMethod(bean, beanDefinition);
        registerBeanDestroyMethod(bean, beanDefinition);
        executeBeanPostProcessor(bean, beanDefinition);
    }

    /**
     * 执行bean获取的方法
     * @param beanClass bean的类型
     * @param findSingleton 是否从单例进行查找
     * @param findPrototype 是否从原型进行查找
     * @return 查找到的bean集合
     * @param <T> bean的类型
     */
    @SuppressWarnings("unchecked")
    private  <T> Collection<T> doGetBeans(Class<T> beanClass, boolean findSingleton, boolean findPrototype) {
        Collection<T> collection = new LinkedList<>();
        for (BeanHolder beanHolder : earlyBeanCreationMap.values()) {
            if (beanClass.isAssignableFrom(beanHolder.getType())) {
                collection.add((T) beanHolder.getObject());
            }
        }

        if (findSingleton) {
            Collection<Object> objects = singletonBeanClassCacheMap.get(beanClass);
            if (objects != null) {
                for (Object object : objects) {
                    if (object != null) {
                        collection.add((T) ((object instanceof PrimaryBeanHolder) ? ((PrimaryBeanHolder) object).getBean() : object));
                    }
                }
            }
        }

        if (findPrototype) {
            Collection<BeanDefinition> beanDefinitions = prototypeBeanClassCacheMap.get(beanClass);
            if (beanDefinitions != null) {
                for (BeanDefinition beanDefinition : beanDefinitions) {
                    Object instance = createBeanInstance(beanDefinition);
                    beanAttributePadding(instance);

                    executeBeanAwareInterfaceMethod(instance, beanDefinition);
                    executeBeanInitializeMethod(instance, beanDefinition);
                    collection.add((T) instance);
                }
            }
        }
        return collection;
    }

    /**
     * 创建bean实例对象
     * @param beanDefinition bean定义对象
     * @param beanCreator bean创建函数
     * @param params bean字段对象值
     * @return bean实例对象
     */
    private Object doCreateBeanInstance(BeanDefinition beanDefinition, Supplier<Object> beanCreator, Object[] params) {
        Object bean = beanCreator.get();
        if (beanDefinition.isProxy()) {
            Constructor<?> constructor = beanDefinition.getConstructor();
            Object proxyObject;
            if (constructor.getParameterCount() == 0 || params.length == 0) {
                proxyObject = proxyObjectContext.createProxyObject(bean, beanDefinition.getProxyType());
            } else {
                proxyObject = proxyObjectContext.createProxyObject(bean, constructor.getParameterTypes(), params, beanDefinition.getProxyType());
            }
            bean = new ProxyObjectHolder(proxyObject, bean);
        }
        return bean;
    }

    /**
     * 创建bean实例对象
     * @param beanDefinition bean定义对象
     * @param beanCreator bean创建函数
     * @return bean实例对象
     */
    private Object doCreateBeanInstance(BeanDefinition beanDefinition, Supplier<Object> beanCreator) {
        return doCreateBeanInstance(beanDefinition, beanCreator, null);
    }

    /**
     *  执行Bean后置处理器方法
     * @param bean bean对象
     * @param beanDefinition bean定义对象
     */
    private void executeBeanPostProcessor(Object bean, BeanDefinition beanDefinition) {
        Collection<BeanPriorityPostProcessor> beanPriorityPostProcessors = getBeans(BeanPriorityPostProcessor.class);
        if (beanPriorityPostProcessors != null && !beanPriorityPostProcessors.isEmpty()) {
            beanPriorityPostProcessors.stream()
                    .sorted(Comparator.comparing(Order::getOrder))
                    .forEach(p -> p.process(bean, beanDefinition.getBeanClass(), this, this));
        }

        Collection<BeanPostProcessor> beanPostProcessors = getBeans(BeanPostProcessor.class);
        if (beanPostProcessors != null && !beanPostProcessors.isEmpty()) {
            beanPostProcessors.stream()
                    .filter(p -> !BeanPriorityPostProcessor.class.isAssignableFrom(p.getClass()))
                    .sorted(Comparator.comparing(Order::getOrder))
                    .forEach(p -> p.process(bean, beanDefinition.getBeanClass(), this, this));
        }
    }

    /**
     * 执行Bean的Aware接口方法
     * @param bean bean对象
     * @param beanDefinition bean定义对象
     */
    private void executeBeanAwareInterfaceMethod(Object bean, BeanDefinition beanDefinition) {
        if (bean instanceof BeanNameAware) {
            ((BeanNameAware) bean).setBeanName(beanDefinition.getBeanName());
        }
        if (bean instanceof ApplicationContextAware) {
            ((ApplicationContextAware) bean).setApplicationContext(this);
        }
        if (bean instanceof ClassLoaderAware) {
            ((ClassLoaderAware) bean).setClassLoader(ClassLoaderUtils.getClassLoader());
        }
        if (bean instanceof EnvironmentAware) {
            ((EnvironmentAware) bean).setEnvironment(getBean(Environment.class));
        }
        executeExtendBeanAwareInterfaceMethod(bean, beanDefinition);
    }

    /**
     * 执行bean初始化方法
     * @param bean bean对象
     * @param beanDefinition bean定义对象
     */
    private void executeBeanInitializeMethod(Object bean, BeanDefinition beanDefinition) {
        if (bean instanceof InitializingBean) {
            try {
                ((InitializingBean) bean).initialize();
            } catch (Exception e) {
                throw new BeanException("Bean Initialize Method Execute Fail, Bean Name[" + beanDefinition.getBeanName()
                        + "], Bean Type[" + beanDefinition.getBeanClass().getName() + "].", e);
            }
        }

        for (Method method : ReflectUtils.findSpecifiedMethod(bean.getClass(), PostConstruct.class, new Class[0], void.class)) {
            try {
                method.invoke(bean);
            } catch (Exception e) {
                throw new BeanException("Bean Initialize Method Execute Fail, Bean Name[" + beanDefinition.getBeanName()
                        + "], Bean Type[" + beanDefinition.getBeanClass().getName() + "].", e);
            }
        }

        // lazy initialized
        if (bean instanceof LazyInitializingBean) {
            lazyBeanProxyInitializedList.add(new LazyInitializingBeanInterfaceProxyInitialized(beanDefinition.getBeanName(),
                    beanDefinition.getBeanClass(), (LazyInitializingBean) bean));
        }

        for (Method method : ReflectUtils.findSpecifiedMethod(bean.getClass(), LazyInitialized.class, new Class[0], void.class)) {
            lazyBeanProxyInitializedList.add(new LazyInitializedAnnotationProxyInitialized(beanDefinition.getBeanName(),
                    beanDefinition.getBeanClass(), bean, method));
        }
    }

    /**
     * 注册bean销毁回调方法
     * @param bean bean对象
     * @param beanDefinition bean定义对象
     */
    private void registerBeanDestroyMethod(Object bean, BeanDefinition beanDefinition) {
        if (bean instanceof DisposableBean) {
            beanProxyDestroyList.add(new DisposableBeanInterfaceProxyDestroy(beanDefinition.getBeanName(),
                    beanDefinition.getBeanClass(), (DisposableBean) bean));
        }

        for (Method method : ReflectUtils.findSpecifiedMethod(bean.getClass(), PreDestroy.class, new Class[0], void.class)) {
            beanProxyDestroyList.add(new PreDestroyAnnotationProxyDestroy(beanDefinition.getBeanName(),
                    beanDefinition.getBeanClass(), bean, method));
        }
    }
}
